<?php
/**
 * Created by PhpStorm.
 * User: longli
 * VX: isa1589518286
 * Date: 2020/04/17
 * Time: 15:27
 * @link http://www.lmterp.cn
 */

namespace app\common\service\platform;

use app\common\library\OrderHelp;
use app\common\library\Tools;
use app\common\model\AccountSyncLog;
use app\common\model\Orders;
use app\common\model\OrdersDetail;
use app\common\model\OrdersTemp;
use app\common\service\orders\OrderService;
use think\exception\DbException;
use think\facade\Log;

/**
 * 速卖通接口服务
 * Class AliexpressService
 * @package app\common\service\aliexpress
 * @link http://gw.api.alibaba.com/dev/doc/intl/api.htm?ns=aliexpress.open&n=api.findOrderListQuery&v=1
 */
class AliexpressService extends BasePlatformService
{

    /**
     * 速卖通 API 请求地址
     * @var string
     */
    const ALIEXPRESS_BASE_URL = "http://gw.api.alibaba.com/openapi";

    /**
     * api 计算签名
     * @var string
     */
    const API_INFO = "param2/1/aliexpress.open/%s/%s";

    /**
     * 获取订单列表
     * @param array $params 请求参数
     * <ul>
     *  <li>string startDate 开始时间</li>
     *  <li>string endDate 结束时间，默认为当前时间</li>
     *  <li>string status 订单状态，默认为等待发货订单（WAIT_SELLER_SEND_GOODS）</li>
     * </ul>
     * @param bool $replace 是否替换原有订单，默认不替换
     * @date 2020/05/12
     * @author longli
     */
    public function getOrderList($params = [], $replace = false)
    {
        Log::info(sprintf("aliexpress 批量同步账号[%d]订单，请求参数: %s", $this->getAccountId(), json_encode($params)));
        $startTime = time(); // 请求开始执行时间
        // 参数校验
        $page = 1;
        $pageSize = 50;
        $createDateStart = $this->converStrDate($params['startDate']);
        $createDateEnd = !empty($params['endDate']) ? $this->converStrDate($params['endDate']) : date('m/d/Y h:i');
        $orderStatus = !empty($params['status']) ? $params['status'] : 'WAIT_SELLER_SEND_GOODS'; // 默认获取等待发货订单
        do
        {
            $args = compact('page', 'pageSize', 'createDateStart', 'createDateEnd', 'orderStatus');
            $orders = $this->getFindOrderListQuery($args); // 请求订单列表
            foreach($orders['OrderItemVO'] as $order)
            {
                $this->pushOrderToTemp($order['orderId'], $order, $replace);
            }
            $page++; // 请求下一页订单
            sleep(1); // 睡眠1秒减少接口请求压力
        }while($orders['totalItem'] > 0);
        // 添加同步日志
        AccountSyncLog::addLog($this->getAccountId(), $startTime, time(), $args);
    }

    /**
     * 通过平台订单号获取订单详情
     * @param string orderId 速卖通订单号
     * @return array
     * @date 2020/05/13
     * @author longli
     */
    public function getOrderInfoById($orderId)
    {
        Log::info(sprintf("账号[%d], 通过平台订单号: [%s] 获取订单详情", $this->getAccountId(), $orderId));
        return $this->getFindOrderById(['orderId' => $orderId]);
    }

    public function syncOrder(OrdersTemp $ordersTemp)
    {
        // @todo 未处理
        $data = $ordersTemp->order_info;
        $info = [];
        foreach($data['productList'] as $item)
        {
            $info[] = [
                "item_id"       => $item['productId'], // 商品 id
                "qty"           => $item['productCount'], // 数量
                "return_qty"    => 0, // 取消数量
                "price"         => $item['totalProductAmount']['amount'], // 售价
                "platform_sku"  => $item['skuCode'], // sku
                "name"          => $item['productName'], // 产品名称
                "image_url"     => $item['productImgUrl'], // 图片地址
                "url"           => $item['productSnapUrl'], // 商品链接
                'attr'          => $item['productStandard'], // 商品属性
                "customer_remark"=>$item['memo'], // 平台备注
            ];
        }
        $platform = $this->getAccountById($ordersTemp->account_id)->platform;
        $address = & $data['receiptAddress'];
        $order = [
            "order_no"                  => $ordersTemp->order_no,
            "account_id"                => $ordersTemp->account_id,
            "platform_name"             => $platform->name, // 平台名称
            "order_platform_status"     => $data['orderStatus'], // 订单在平台的状态
            "buyer_gender"              => null, // 客户性别
            "buyer_company"             => null, // 客户公司
            'consignee'                 => $address['contactPerson'], // 收件人
            "buyer_first_name"          => '', // 客户名称
            "buyer_last_name"           => '', // 客户名称
            "buyer_phone"               => '', // 电话
            "buyer_country"             => '', // 国家
            "buyer_country_code"        => '', // 国家编码
            'buyer_province'            => '', // 买家所在省，州
            "buyer_district"            => '', // 区
            "buyer_city"                => '', // 城市
            "buyer_post_code"           => '', // 邮编
            "buyer_address_1"           => '', // 买家收货地址1
            "buyer_address_2"           => '', // 买家收货地址2
            "buyer_address_3"           => '', // 买家收货地址3
            "buyer_email"               => '', // 买家邮箱
            "shipping_price"            => null, // 订单运费
            "order_source_create_time"  => null, // 订单在平台生成的时间
            "latest_delivery_time"      => null, // 最迟发货时间
            "payment_method"            => '', // 支付方式
            "order_price"               => null, // 订单金额
            "total_price"               => null, // 订单总金额
            "order_pay_time"            => null, // 订单支付时间
            "currency"                  => '', // 币种
            "invoice_type"              => '', // 发票种类
            "invoice_title"             => '', // 发票抬头
            "invoice_detail"            => '', // 发票详情
            "track_num"                 => '', // 追踪号
            "shipping_method"           => '', // 追踪号
            "platform_remark"           => '', // 买家备注信息
            "order_detail" => $info,
        ];
        return OrderService::getInstance()->addOrder($order);
    }

    /**
     * 把常规日期转换为速卖通日期
     * @param string $strDate 日期格式
     * @return string 转换后的日期
     * @date 2020/05/12
     * @author longli
     */
    protected function converStrDate($strDate = '')
    {
        if(empty($strDate)) return date('m/d/Y h:i');
        return date('m/d/Y h:i', strtotime($strDate));
    }

    /**
     * 计算签名
     * @param string $apiInfo api计算签名
     * @param array $params 参数
     * @param string $secret 私钥
     * @return string
     * @date 2020/04/18
     * @author longli
     */
    protected function getSign($apiInfo, array $params = [], $secret = '')
    {
        $signs = [];
        foreach($params as $key => $val)
        {
            $signs[] = "$key$val";
        }
        asort($signs);
        $sign = $apiInfo . implode('', $signs);
        return strtoupper(bin2hex(hash_hmac("sha1", $sign, $secret, true)));
    }

    /**
     * 构建请求 URL
     * @param string $api 要请求的 api, 比如: findOrderListQuery 订单接口列表
     * @param array $params 请求参数
     * @return string
     * @date 2020/04/19
     * @author longli
     * @example
     * http://gw.api.alibaba.com/openapi/param2/1/aliexpress.open/
     * api.findAeProductById/100000?productId=1&_aop_timestamp=1375703483649
     * &access_token=HMKSwKPeSHB7Zk7712OfC2Gn1-kkfVsaM-P&_aop_signature=DE1D9BDE00646F5C1704930003C9FC011AADDE25
     */
    public function buildUrl($api, array $params = [])
    {
        $account = $this->getAccount();
        if(!Tools::startWith($api, 'alibaba.ae') || !Tools::startWith($api, 'api.')) $api = "api.$api";
        $apiInfo = sprintf(self::API_INFO, $api, $account->token->appkey);
        if(empty($params['access_token'])) $params['access_token'] = $account->token->access_token;
        $sign = $this->getSign($apiInfo, $params, $account->token->secret);
        return self::ALIEXPRESS_BASE_URL . "/$apiInfo?" . http_build_query($params)
            . "&access_token={$account->token->access_token}&_aop_signature={$sign}";
    }

    public function __call($method, $args = [])
    {
        // 校验参数
        if(Tools::startWith($method, 'post', false)
            || Tools::startWith($method, 'get', false)
            || empty($args)
            || !is_array($args[0])) return false;
        // 是否为 post 请求，默认 get
        $m = Tools::startWith($method, 'post', false) ? 'Post' : 'Get';
        // 获取请求 api 接口
        $api = lcfirst(substr($method, strlen($m)));
        $func = Tools::class . "::curl$m";
        $url = $this->buildUrl($api, $args[0]);
        $response = call_user_func_array($func, [$url]);
        if(!$response['status'])
        {
            Log::info(sprintf("账号[%d]，请求方法[%s]，错误信息: %s", $this->getAccountId(), $method, $response['data']));
            return false;
        }
        if(Tools::isJson($response['data'], $data)) return $data;
        return $response['data'];
    }
}